home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-11-04 | 12.1 KB | 474 lines | [TEXT/MPS ] |
- /*
- Apple Macintosh Developer Technical Support,
- TRandom 1.0 - Saturday, October 5, 1991 18:26:35
-
- TRandom.cp - C++ source
-
- Copyright © 1991 Apple Computer, Inc.
- All rights reserved.
-
- TRandom is a stackbased utility class for random number generation.
- TRandom.cp contains the member function implementations for TRandom.
- */
-
- // INCLUDE FILES -----------------------------------------------------------------------
-
- #include "Random.h"
-
-
- // CLASS MEMBER FUNCTIONS IMPLEMENTATIONS ----------------------------------------------
-
- // GENERAL -----------------------------------------------------------------------------
-
- TRandom::TRandom(eRandType theType, long theSeed,
- unsigned short low, unsigned short high)
- {
- if(theSeed == 1) // no seed value
- this->ShuffleSeed(); // no first value, random value
- else
- this->SetSeedValue(theSeed); // programmer defined seed
-
- this->fLow = low;
- this->fHigh = high;
- this->fRange = high - low;
-
- Boolean fState = this->IRandom(theType); // initialize the object
- }
-
-
- TRandom::TRandom(const TRandom& other) // copy constructor
- {
- register int x;
-
- // fill in the needed fields with values from the referenced object
-
- this->fGenerator = other.fGenerator;
- this->fAlgorithm = other.fAlgorithm;
- this->fLow = other.fLow;
- this->fHigh = other.fHigh;
- this->fRange = other.fRange;
- this->fSeed = other.fSeed;
- this->fState = other.fState;
- this->fPrevNum = other.fPrevNum;
-
- for(x = 0; x < eSHUFFLETABLE; x++) // copy the values from array
- this->fShuffleBuf[x] = other.fShuffleBuf[x];
- }
-
-
- TRandom& TRandom::operator=(const TRandom& other) // assignment operator
- {
- register int x;
-
- // fill in the needed fields with values from the referenced object
-
- this->fGenerator = other.fGenerator;
- this->fAlgorithm = other.fAlgorithm;
- this->fLow = other.fLow;
- this->fHigh = other.fHigh;
- this->fRange = other.fRange;
- this->fSeed = other.fSeed;
- this->fState = other.fState;
- this->fPrevNum = other.fPrevNum;
-
- for(x = 0; x < eSHUFFLETABLE; x++) // copy the values from array
- this->fShuffleBuf[x] = other.fShuffleBuf[x];
-
- return *this;
- }
-
-
- TRandom::~TRandom(){} // virtual destructor, should
- // *not* be inlined
-
-
- Boolean TRandom::IRandom(eRandType theType)
- {
- switch(theType){
- case MACOS:
- qd.randSeed = this->GetSeedValue();
- this->fGenerator = &TRandom::MacRandom; // quick init
- this->fAlgorithm = MACOS;
- break;
- case QUICK:
- this->ShuffleSeed();
- qd.randSeed = this->GetSeedValue();
- this->fGenerator = &TRandom::QuickRandom;
- this->fAlgorithm = QUICK;
- break;
- case SHUFFLE:
- qd.randSeed = this->GetSeedValue();
- this->fGenerator = &TRandom::ShuffleRandom;
- this->fAlgorithm = SHUFFLE;
- this->InitShuffleRandom();
- break;
- case PM:
- this->fGenerator = &TRandom::ParkMiller;
- this->fAlgorithm = PM;
- break;
- default:
- return false; // should never get here...
- };
- return true;
- }
-
-
- // MAC TOOLBOX TRAP MEMBER FUNCTIONS ---------------------------------------------------
- unsigned short TRandom::MacRandom() // Toolbox random number generator
- {
- register unsigned short temp;
-
- temp = short(Random()); // scale to 0 - 65536
-
- return( ( (temp * this->fRange) /e16BIT) + this->fLow);
- }
-
-
- // ASSEMBER QUICK ROUTINE MEMBER FUNCTIONS --------------------------------------------
-
- unsigned short TRandom::QuickRandom() // quick asm random generator
- {
- register unsigned short temp;
-
- temp = short(AsmRandom()); // scale to 0 - 65536
-
- return( ( (temp * this->fRange) /e16BIT) + this->fLow);
- }
-
-
- // SHUFFLE RANDOM MEMBER FUNCTIONS ----------------------------------------------------
-
- TRandom& TRandom::InitShuffleRandom()
- {
- register short i;
-
- for(i = 0; i < eSHUFFLETABLE; i++)
- Random(); // shuffle the random generator
- for(i = 0; i < eSHUFFLETABLE; i++)
- this->fShuffleBuf[i] = Random(); // fill the buffer
-
- this->fPrevNum = Random(); // get first 'later' value
- return *this;
- }
-
-
- unsigned short TRandom::ShuffleRandom()
- {
- register unsigned short index;
-
- index = (this->fPrevNum * eSHUFFLETABLE) /e16BIT;
- this->fPrevNum = this->fShuffleBuf[index]; // get random number from table
- this->fShuffleBuf[index] = Random(); // new random table entry
-
- return( ( (this->fPrevNum * this->fRange) /e16BIT) + this->fLow);
- }
-
-
-
- // PARK&MILLER MEMBER FUNCTIONS -------------------------------------------------------
-
- unsigned short TRandom::ParkMiller() // CACM Oct 1988
- {
- unsigned short high, low;
- register unsigned short temp;
-
- high = short (this->fSeed / ePM3);
- low = short (this->fSeed % ePM3);
- temp = (ePM2 * low) - (ePM1 * high);
-
- if( temp > 0 )
- this->fSeed = temp;
- else
- this->fSeed = temp + eACM_MAX;
-
- return( ( (temp * this->fRange) /e16BIT) + this->fLow);
- }
-
- // TEST FUNCTIONS --------------------------------------------------------------------
-
- /* This is the TestRandomClass test suite:
-
- 1. create an instance of the TGenerator class, and produce a random
- number with each included algorithm
- 2. CreatecBIGNUMamount random numbers with each algorithm, and count the time
- 3. Create twice x amount random numbers from the same seed, and compare
- if the values are the same.
- 4. Test mutator class reference passing (syntax check)
- 5. Test of copy constructor
- 6. Test of assignment operator overload
-
- Notes:
- Why cerr:s everywhere, instead of cout:s? Well, cerr is not buffered.
- */
-
- unsigned long timeStart; // global timing
-
- void TRandom::TestRandomClass()
- {
- // local variables
-
- const short cARRAYSIZE = 80; // 200 is a nice size
- const long cBIGNUM = 1000; //cBIGNUM= 1000000 takes about 40 sec
-
- unsigned short val;
- long x;
- unsigned short array1[cARRAYSIZE], array2[cARRAYSIZE];
-
- InitGraf((Ptr) &qd.thePort); // Initialize grafport!
-
-
- // First initial quick test of the toolbox value
-
- qd.randSeed = TickCount();
- long xx = Random();
- cerr << "Normal Toolbox Random = " << xx << '\n';
-
-
- // 1. Create an instance of each TRandom class -----------------------------
-
- TRandom aRandom;
- val = aRandom.Next();
- cerr << "Toolbox aRandom.Next = " << val << "\n";
-
-
- aRandom.SetRandomGenerator(TRandom::QUICK);
- val = aRandom.Next();
- cerr <<"Quick aRandom.Next = " << val << '\n';
-
-
- aRandom.SetRandomGenerator(TRandom::SHUFFLE);
- val = aRandom.Next();
- cerr <<"Shuffle aRandom.Next = " << val << '\n';
-
- aRandom.SetRandomGenerator(TRandom::PM);
- val = aRandom.Next();
- cerr <<"PM aRandom.Next = " << val << '\n';
-
- // 2. Efficiency test, docBIGNUMtimes random numbers and return the time
-
- cerr << "Doing " <<cBIGNUM<<" random numbers of each class...this will take some time\n";
-
- // Toolbox Random
-
- aRandom.SetRandomGenerator(TRandom::MACOS);
- GetDateTime(&timeStart);
- for(x = 0; x <= cBIGNUM; x++){
- val = aRandom.Next();
- #if DEBUG
- cerr << "Toolbox Random " << x <<" = " << val << '\n';
- #endif
- SpinCursor(1);
- }
- CalcTime("Toolbox");
-
-
-
- // Quick Random
-
- aRandom.SetRandomGenerator(TRandom::QUICK);
- GetDateTime(&timeStart);
- for(x = 0; x <= cBIGNUM; x++){
- val = aRandom.Next();
- #if DEBUG
- cerr << "Quick Random " << x <<" = " << val << '\n';
- #endif
- SpinCursor(1);
- }
- CalcTime("Quick");
-
-
- // Shuffle Random
-
- aRandom.SetRandomGenerator(TRandom::SHUFFLE);
- GetDateTime(&timeStart);
- for(x = 0; x <= cBIGNUM; x++){
- val = aRandom.Next();
- #if DEBUG
- cerr << "Shuffle Random " << x <<" = " << val << '\n';
- #endif
- SpinCursor(1);
- }
- CalcTime("Shuffle");
-
-
- // PM Random
-
- aRandom.SetRandomGenerator(TRandom::PM);
- GetDateTime(&timeStart);
- for(x = 0; x <= cBIGNUM; x++){
- val = aRandom.Next();
- #if DEBUG
- cerr << "PM Random " << x <<" = " << val << '\n';
- #endif
- SpinCursor(1);
- }
- CalcTime("PM");
-
-
- // 3. Performance test, create twice the random numbers with the same
- // original seed, and compare the results, signal if they differ
-
- long definedSeed;
-
- cerr << "Performance test, create from same seed twice and compare...\n";
-
-
- // MACOS Random Performance test
-
- cerr <<"MacOS Random...";
- aRandom.SetRandomGenerator(TRandom::MACOS);
-
- aRandom.ShuffleSeed(); // get new seed
- definedSeed = aRandom.GetSeedValue(); // store it
-
- aRandom.SetSeedValue(definedSeed); // back to first seed
-
- for(x = 0; x < cARRAYSIZE; x++) // fill array1
- array1[x] = aRandom.Next();
-
- aRandom.SetSeedValue(definedSeed); // back to first seed
- for(x = 0; x < cARRAYSIZE; x++) // fill array2
- array2[x] = aRandom.Next();
-
- for(x = 0; x < cARRAYSIZE; x++){ // compare
- if(array1[x] != array2[x]){
- cerr << "problems with Toolbox values....\n";
- cerr << "x = " << x <<",array1 = " << array1[x]
- << ", array2 = " << array2[x] << '\n';
- } else cerr <<".";
- }
- cerr <<"\n";
-
-
- // Quick Random Performance test
-
- cerr <<"Quick Random...";
- aRandom.SetRandomGenerator(TRandom::QUICK);
-
- aRandom.ShuffleSeed(); // get new seed
- definedSeed = aRandom.GetSeedValue(); // store it
-
- aRandom.SetSeedValue(definedSeed); // back to first seed
-
- for(x = 0; x < cARRAYSIZE; x++) // fill array1
- array1[x] = aRandom.Next();
-
- aRandom.SetSeedValue(definedSeed); // back to first seed
- for(x = 0; x < cARRAYSIZE; x++) // fill array2
- array2[x] = aRandom.Next();
-
- for(x = 0; x < cARRAYSIZE; x++){ // compare
- if(array1[x] != array2[x]){
- cerr << "problems with Quick values....\n";
- cerr << "x = " << x <<",array1 = " << array1[x]
- << ", array2 = " << array2[x] << '\n';
- } else cerr <<".";
- }
- cerr <<"\n";
-
-
-
- // Shuffle Random Performance test
-
- cerr <<"Shuffle Random...";
- TRandom rand1(TRandom::SHUFFLE);
- TRandom rand2(TRandom::SHUFFLE);
-
- aRandom.ShuffleSeed(); // get new seed
- definedSeed = aRandom.GetSeedValue(); // store it
-
- rand1.SetSeedValue(definedSeed); // back to first seed
-
- for(x = 0; x < cARRAYSIZE; x++) // fill array1
- array1[x] = rand1.Next();
-
- rand2.SetSeedValue(definedSeed); // back to first seed
- for(x = 0; x < cARRAYSIZE; x++) // fill array2
- array2[x] = rand2.Next();
-
- for(x = 0; x < cARRAYSIZE; x++){ // compare
- if(array1[x] != array2[x]){
- cerr << "problems with Quick values....\n";
- cerr << "x = " << x <<",array1 = " << array1[x]
- << ", array2 = " << array2[x] << '\n';
- } else cerr <<".";
- }
- cerr <<"\n";
-
-
-
-
- // Park-Miller
-
- cerr <<"PM Random...";
- aRandom.SetRandomGenerator(TRandom::PM);
-
- aRandom.ShuffleSeed(); // get new seed
- definedSeed = aRandom.GetSeedValue(); // store it
-
- aRandom.SetSeedValue(definedSeed); // back to first seed
-
- for(x = 0; x < cARRAYSIZE; x++) // fill array1
- array1[x] = aRandom.Next();
-
- aRandom.SetSeedValue(definedSeed); // back to first seed
-
- for(x = 0; x < cARRAYSIZE; x++) // fill array2
- array2[x] = aRandom.Next();
-
- for(x = 0; x < cARRAYSIZE; x++){ // compare
- if(array1[x] != array2[x]){
- cerr << "problems with PM values....\n";
- cerr << "x = " << x <<",array1 = " << array1[x]
- << ", array2 = " << array2[x] << '\n';
- } else cerr <<".";
- }
- cerr <<"\n";
-
-
- // 4. Test mutator class reference passing (syntax check) --------------
-
- aRandom.SetRandomGenerator(TRandom::MACOS).ShuffleSeed();
-
-
- // 5. Test of copy constructor -----------------------------------------
-
- cerr <<"\nTest of copy constructor\n";
-
- TRandom bRandom(aRandom);
-
- cerr << "Seed from aRandom = " << aRandom.GetSeedValue() << "\n";
- cerr << "Seed from bRandom = " << bRandom.GetSeedValue() << "\n";
- cerr << "Rand val from aRandom = " << aRandom.Next() << "\n";
- cerr << "Rand val from bRandom = " << bRandom.Next() << "\n";
-
-
- // 6. Test of assignment operator overload
-
- cerr <<"\nTest of assignment operator overload\n";
-
- TRandom cRandom = aRandom;
-
- cerr << "Seed from aRandom = " << aRandom.GetSeedValue() << "\n";
- cerr << "Seed from cRandom = " << cRandom.GetSeedValue() << "\n";
- cerr << "Rand val from aRandom = " << aRandom.Next() << "\n";
- cerr << "Rand val from cRandom = " << cRandom.Next() << "\n";
-
- // the end -------------------------------------------------------------
-
- cerr <<"The end of the TRandom Test!\n";
-
- }
-
- // calculate Time
-
- void TRandom::CalcTime(const char* string)
- {
- unsigned long totalTime, timeEnd;
-
- GetDateTime(&timeEnd);
- totalTime = timeEnd - timeStart;
- cerr <<"Time for \t" << string <<"\t= " << totalTime <<'\n';
- }
-
- // THE END ----------------------------------------------------------------------------